ποΈGitΠ―ΡΠ°ποΈ
Node / meshtastic / Meshtastic-Android / files / specs / 20260511-211823-compose-screenshot-testing / data-model.md
specs/20260511-211823-compose-screenshot-testing/data-model.md bc5cf83df7fd6b405ffc521d7c3ed4e1f3e8271a (bc5cf83d) Text, 6.32 KB
Data Model: Compose Preview Screenshot Testing
Feature: 018-compose-screenshot-testing
Date: 2026-05-08
Entities
This feature does not introduce database entities or domain models. The "data" consists of file-system artifacts managed by the CST plugin and Gradle build system.
Preview Composable
A T383838@Composable function annotated with T383838@Preview or T383838@PreviewLightDark in a KMP module's T383838commonMain source set.
βββββββββββββββββ¬βββββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Field β Type β Description β
βββββββββββββββββΌβββββββββββββββββββββββββββββββΌββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Function name β Kotlin function β Unique within its file; naming convention T383838*Previβ¦ β
β Visibility β T383838internal or T383838public β Must NOT be T383838private β needs to be importable by T383838β¦ β
β Annotations β T383838@Preview / T383838@PreviewLightDark β From T383838androidx.compose.ui.tooling.preview (CMP 1.β¦ β
β Theme wrapper β T383838AppTheme { ... } β Required β ensures M3 theming in reference images β
β Sample data β Hardcoded synthetic β Never real user data, PII, or location coordinatβ¦ β
β Module β KMP module path β e.g. T383838core:ui, T383838feature:messaging β
βββββββββββββββββ΄βββββββββββββββββββββββββββββββ΄ββββββββββββββββββββββββββββββββββββββββββββββββββββ
Validation rules:
β’ Function must be annotated with at least one preview annotation
β’ Content must be wrapped in T383838AppTheme
β’ No ViewModel, DI, or network dependencies
β’ Must compile on all KMP targets (lives in T383838commonMain)
Screenshot Test Wrapper
A T383838@Composable function in the T383838screenshotTest source set of the T383838screenshot-tests module.
βββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββ
β Field β Type β Description β
βββββββββββββββββΌββββββββββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββ€
β Function name β Kotlin function β Convention: T383838{PreviewName}Screenshotβ¦ β
β Annotations β T383838@PreviewTest + T383838@Preview/T383838@PreviewLightDark β T383838@PreviewTest from T383838com.android.toolsβ¦ β
β Body β Composable call β Delegates to the target preview comβ¦ β
βββββββββββββββββ΄ββββββββββββββββββββββββββββββββββββββββββββ΄βββββββββββββββββββββββββββββββββββββββ
Validation rules:
β’ Must have T383838@PreviewTest annotation (required since CST alpha10)
β’ Must also have T383838@Preview or T383838@PreviewLightDark (tells CST what configurations to render)
β’ Renaming the function invalidates existing reference images
Reference Image
A PNG file generated by the CST T383838update{Variant}ScreenshotTest task.
βββββββββββββ¬ββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Field β Type β Description β
βββββββββββββΌββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β File name β String β T383838{package}.{FunctionName}_{hash1}_{hash2}_{index}.png β
β Location β File path β T383838screenshot-tests/src/screenshotTestDebug/reference/ β
β Format β PNG β Lossless raster image β
β Variant β Build variant β e.g. T383838fdroidDebug, T383838debug β
βββββββββββββ΄ββββββββββββββββ΄βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Validation rules:
β’ Must be committed to version control
β’ Generated on a consistent OS/JDK to avoid rendering differences
β’ Validated by T383838validate{Variant}ScreenshotTest against current rendered output
Diff Report
An HTML report generated by the CST T383838validate{Variant}ScreenshotTest task when validation fails.
βββββββββββββββ¬ββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Field β Type β Description β
βββββββββββββββΌββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Location β File path β T383838screenshot-tests/build/reports/screenshotTest/preview/{variant}/indexβ¦ β
β Content β HTML β Side-by-side reference/actual/diff images with percentage difference β
β CI artifact β Uploaded β Available as GitHub Actions build artifact on failure β
βββββββββββββββ΄ββββββββββββ΄βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Relationships
T282828
Preview Composable (commonMain)
β imported by
Screenshot Test Wrapper (screenshotTest source set)
β rendered by CST plugin β generates
Reference Image (version-controlled PNG)
β compared by validate task β produces on diff
Diff Report (HTML, CI artifact)
β selected images copied by
Docs Asset (consumed by spec 003 docs pipeline)
State Transitions
Reference images have a simple lifecycle:
T282828
[Not Exists] β update task β [Generated] β commit β [Tracked]
[Tracked] β UI changes β validate fails β [Stale]
[Stale] β update task β [Updated] β commit β [Tracked]
[Tracked] β preview deleted β [Orphaned] β manual cleanup β [Removed]
Version Catalog Entries
New entries required in T383838gradle/libs.versions.toml:
T282828
Tff7b72[Tff7b72versionsTff7b72]
Te6edf3compose-screenshot Tff7b72= Ta5d6ff"Ta5d6ff0.0.1-alpha14Ta5d6ff"
Tff7b72[Tff7b72librariesTff7b72]
Te6edf3screenshot-validation-api Tff7b72= Tb4b4b4{ Te6edf3group Tb4b4b4= Ta5d6ff"Ta5d6ffcom.android.tools.screenshotTa5d6ff"Tb4b4b4, Te6edf3name Tb4b4b4= Ta5d6ff"Ta5d6ffscreenshot-validation-apiTa5d6ff"Tb4b4b4, Te6edf3versionTb4b4b4.Te6edf3ref Tb4b4b4= Ta5d6ff"Ta5d6ffcompose-screenshotTa5d6ff" Tb4b4b4}
Tff7b72[Tff7b72pluginsTff7b72]
Te6edf3compose-screenshot Tff7b72= Tb4b4b4{ Te6edf3id Tb4b4b4= Ta5d6ff"Ta5d6ffcom.android.compose.screenshotTa5d6ff"Tb4b4b4, Te6edf3versionTb4b4b4.Te6edf3ref Tb4b4b4= Ta5d6ff"Ta5d6ffcompose-screenshotTa5d6ff" Tb4b4b4}
Configuration Properties
ββββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββ
β Property β File β Value β
ββββββββββββββββββββββββββββββΌββββββββββββββββββββββββββββββββββββΌββββββββββββββββββββββββββββββββββ€
β T383838android.experimental.enabβ¦ β T383838gradle.properties β T383838true β
β T383838experimentalProperties["aβ¦ β T383838screenshot-tests/build.gradle.kts β T383838true β
β T383838imageDifferenceThreshold β T383838screenshot-tests/build.gradle.kts β T3838380.0005f β
β T383838namespace β T383838screenshot-tests/build.gradle.kts β T383838org.meshtastic.screenshot.tests β
ββββββββββββββββββββββββββββββ΄ββββββββββββββββββββββββββββββββββββ΄ββββββββββββββββββββββββββββββββββ
Existing Preview Inventory
Modules with existing previews (require audit)
ββββββββββββββββββββββββββ¬ββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββ¬βββββββββββββββββ
β Module β Preview count β Files β Key issues β
ββββββββββββββββββββββββββΌββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββΌβββββββββββββββββ€
β T383838core:ui β ~40+ β ~25 component files + T383838AlertPreviews.kt β Mixed theme wβ¦ β
β T383838feature:messaging β 6 β 4 files β Good β uses T383838Aβ¦ β
β T383838feature:node β 14 β 5 files β T383838NodeDetailPreβ¦ β
β T383838feature:wifi-provision β 19 β 2 files β Excellent covβ¦ β
β T383838feature:settings β 3 β 3 files (all T383838androidMain) β Need T383838commonMaβ¦ β
β T383838feature:intro β 1 β 1 file (T383838androidMain) β Need T383838commonMaβ¦ β
ββββββββββββββββββββββββββ΄ββββββββββββββββ΄βββββββββββββββββββββββββββββββββββββββββ΄βββββββββββββββββ
Modules needing new previews
βββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Module β Primary components to preview β
βββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β T383838feature:connections β T383838DeviceListItem, T383838ConnectingDeviceInfo, T383838DisconnectButton, T383838DeviceLβ¦ β
β T383838feature:firmware β T383838FirmwareUpdateScreen and sub-components β
β T383838feature:settings (commonMain) β Settings sections currently only previewed in T383838androidMain β
β T383838feature:intro (commonMain) β Welcome/onboarding screen composables currently only previewed β¦ β
βββββββββββββββββββββββββββββββββ΄βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Modules deferred
βββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Module β Reason β
βββββββββββββββββββββΌββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β T383838feature:map β Platform-specific map renderers don't work in CST preview context β
β T383838feature:widget β Glance composables are incompatible with CST β
β T383838feature:discovery β No UI composables β
β T383838feature:metrics β No UI composables (metrics embedded in T383838feature:node) β
β T383838feature:auto β No UI composables β
β T383838feature:docs β No UI composables β
βββββββββββββββββββββ΄ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Served by rngit 1.5.4 - Generated in 0.04s